#!/usr/bin/env python
# -*- coding:utf-8 -*-

# 高阶函数
"""
def add(x,y,f):
    return f(x) + f(y)

print(add(-5,6,abs))
"""

# map用法
"""
def f(x):
    return x * x

r = map(f,[1,2,3,4,5,6,7,8,9])
print(list(r))
'''
map()传入的第一个参数是f,即函数对象本身. 由于结果r是一个Iterator,Iterator是惰性序列.
通过list()函数让它把整个序列都计算出来并返回一个list.
'''
print(list(map(str,[1,2,3,4,5,6,8,9])))
"""

# reduce用法
# 对一个序列求和
"""
from functools import reduce
def add(x,y):
    return x + y

print(reduce(add,[1,3,5,7,9]))


# 把序列[1,3,5,7,9]变换成整数13579
from functools import reduce
def fn(x,y):
    return x * 10 + y

print(reduce(fn,[1,3,5,7,9]))
"""


# 把str转换为int的函数
"""
from functools import reduce
def fn(x,y):
    return x * 10 + y

def char2sum(s):
    return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]

print(reduce(fn,map(char2sum,'13579')))


# 整理成一个str2int的函数
from functools import reduce
def str2int(s):
    def fn(x,y):
        return x * 10 + y
    def char2sum(s):
        return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]
    return reduce(fn,map(char2sum,s))

print(str2int('100'))   
"""


# 用lambda函数简化
"""
from functools import reduce
def char2num(s):
    return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]

def str2int(s):
    return reduce(lambda x, y: x * 10 + y,map(char2num,s))    

print(str2int('300'))
"""


# 在一个list中,删掉偶数,只保留奇数
"""
def is_odd(n):
    return n % 2 == 1

print(list(filter(is_odd,[1,2,4,5,6,7,8,9,10,15])))
"""

# 把一个序列中的空字符串删掉.
"""
def not_empty(s):
    return s and s.strip()

print(list(filter(not_empty,['A','','B',None,'C',' '])))
"""


# sorted排序,接收key函数实现自定义排序.
"""
print(sorted([36,5,-10,9,-1],key=abs))
# sorted传入key函数,实现忽略大小写的排序
print(sorted(['bob','about','Zoo','Credit'],key=str.lower))

# 进行反向排序,传入第三个参数reverse=True).
print(sorted(['bob','about','Zoo','Credit'],key=str.lower,reverse=True))
"""

# 不立刻求和,根据需要再计算.不返回求和的结果,而是返回求和的函数.
"""
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

# 调用lazy_sum()时,返回的不是求和结果,而是求和函数.
f = lazy_sum(1,3,5,7,9)
print(f()) # 调用函数f时,真正计算求和的结果.
'''
说明: 在函数lazy_sum中定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,
当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为闭包.
'''
"""


# 闭包
"""
def count():
    fs = []
    for i in range(1,4):
        def f():
            return i*i
        fs.append(f)
    return fs

f1,f2,f3 = count()
# 每次循环,都创建一个新的函数,返回创建的3个函数.
print(f1(),'==',f2(),'--',f3())
# 返回的函数引用了变量i,但它并不是立刻执行,等到3个函数都返回时,它们所引用的变量i已经变成了3,最终结果为9.
"""

"""
def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1,4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs

f1,f2,f3 = count()
print(f1(),'===',f2(),'---',f3())
"""



# 匿名函数
"""
f = lambda x: x * x
print(f)
print(f(5))

#  可以把匿名函数作为返回值返回.
def build(x,y):
    return lambda: x * x + y * y

print(build(10,20))
"""


# 装饰器
"""
def now():
    print('2015-3-25')

f = now
f()
print(now.__name__)
print(f.__name__)
"""


# 定义一个能打印日志的decorator.
"""
def log(func):
    def wrapper(*args,**kw):
        print('call {}:'.format(func.__name__))
        return func(*args,**kw)
    return wrapper
'''
log是一个装饰器decorator,所以接受一个函数作为参数,并返回一个函数.
'''
@log   # 把@log放到now()函数定义出,相当于执行: now = log(now)
def now():
    print('2015-3-25')
# 调用now()函数,不仅会运行now()函数本身.
print(now())
'''
log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,
只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,
即在log()函数中返回的wrapper()函数.
wrapper()函数的参数定义是(*args,**kw),因此,wrapper()函数可以接受任意参数的调用.
在wrapper()函数内,首先打印日志,再紧接着调用原始函数.
'''
"""



# 要自定义log的文本
"""
def log(text):
    def decorator(func):
        def wrapper(*args,**kw):
            print('{} {}():'.format(text,func.__name__))
            return func(*args,**kw)
        return wrapper
    return decorator

# 3层嵌套的decorator用法:
@log('execute')
def now():
    print('2019-4-11')

print(now())
print('=='*20)
# 3层嵌套的效果:
now = log('execute')(now)
print(now())
'''
首先执行log('execute'),返回的是decorator函数,再调用返回的函数,
参数是now函数,返回值是wrapper函数.

函数也是对象,它有__name__等属性,经过装饰器装饰之后的函数,__name__从原来的now变成了wrapper.
'''
"""

# 一个完整的decorator的写法
"""
import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args,**kw):
        print('call {}:'.format(func.__name__))
        return func(*args,**kw)
    return wrapper


# 针对带参数的decorator
import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args,**kw):
            print('{}={}:'.format(text,func.__name__))
            return func(*args,**kw)
        return wrapper
    return decorator

"""



# 偏函数
"""
print(int('12345'))
# int()函数提供base参数.
print(int('12345',base=8))
print(int('12345',16))

print('--'*20)
# 转换大量二进制字符串
def int2(x,base=2):
    return int(x,base)

print(int2('1000000'))
print(int2('1010101'))
"""

import functools
int2 = functools.partial(int,base=2)
print(int2('1000000'))
print(int2('1010101'))
